﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Xml.Serialization;
using cndp.Model.IModel;

namespace cndp.Model
{
    
    ///<summary>
    ///Contest - Contestklassen innehåller information om en tävling, vilka grenar en tävling har m.m.
    ///</summary>
    [Serializable]
    public class Contest : IContest
    {
        #region Constructor

        public Contest(string name, int id, string location, string startTime, string finishTime, string deadlineDate,
            string contestAdministrator)
        {
            Name = name;
            Id = id;
            Location = location;
            StartTime = startTime;
            FinishTime = finishTime;
            DeadlineDate = deadlineDate;
            ContestAdministrator = contestAdministrator;
        }

        public Contest()
        {
        }

        #endregion

        #region Variabels/Properties

        [XmlElement("NAME")]
        public string Name { get; set; }

        [XmlElement("ID")]
        public int Id { get; set; }

        [XmlElement("LOCATION")]
        public string Location { get; set; }

        [XmlElement("START_TIME")]
        public string StartTime { get; set; } //yyyy-mm-dd tt:tt ex. 2015-01-20 20:00

        [XmlElement("FINISH_TIME")]
        public string FinishTime { get; set; }

        [XmlElement("DEADLINE_DATE")]
        public string DeadlineDate { get; set; } //åååå-mm-dd

        [XmlElement("CONTEST_ADMINISTRATOR")]
        public string ContestAdministrator { get; set; }

        [XmlElement(typeof (Event))] public BindingList<Event> EventList = new BindingList<Event>();

        [XmlElement(typeof (Diver))] public BindingList<Diver> DiverRegister = new BindingList<Diver>();

        [XmlElement(typeof (Judge))] public BindingList<Judge> JudgeRegister = new BindingList<Judge>();

        #endregion

        #region Methods

        public void AddEvent(int id, string gender, string bracket, double jumpHeight, int rounds, int maxDivers,
            int maxJudges, string startTime,
            string finishTime, bool couple)
        {
            var e = new Event(id, gender, bracket, jumpHeight, rounds, maxDivers, maxJudges, startTime, finishTime,
                couple);
            EventList.Add(e);
        }

        public bool EventlistIsEmpty()
        {
            return EventList.Count == 0;
        }

        public void DeleteEvent(int id)
        {
            var eventFound = FindEventInList(id);
            if (eventFound != null)
            {
                EventList.Remove(eventFound);
            }
            else
            {
                throw new Exception("\n Contest.DeleteEvent - Event with that id was not found");
            }
        }

        public Event FindEventInList(int id)
        {
            var eventFound = EventList.SingleOrDefault(e => e.Id == id);        
            return eventFound;
        }

        public bool EditEvent(Event e)
        {
            for (var i = 0; i < EventList.Count; ++i)
            {
                if (EventList[i].Id == e.Id)
                {
                    if (e.Gender != null)
                    {
                        EventList[i].Gender = e.Gender;
                    }
                    if (e.Bracket != null)
                    {
                        EventList[i].Bracket = e.Bracket;
                    }
                    if (e.JumpHeight != null)
                    {
                        EventList[i].JumpHeight = e.JumpHeight;
                    }
                    if (e.Rounds != null)
                    {
                        EventList[i].Rounds = e.Rounds;
                    }
                    if (e.MaxDivers != null)
                    {
                        EventList[i].MaxDivers = e.MaxDivers;
                    }
                    if (e.MaxJudges != null)
                    {
                        EventList[i].MaxJudges = e.MaxJudges;
                    }
                    if (e.StartTime != null)
                    {
                        EventList[i].StartTime = e.StartTime;
                    }
                    if (e.FinishTime != null)
                    {
                        EventList[i].FinishTime = e.FinishTime;
                    }
                    return true;
                }
            }
            return false;
        }

        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            var objAsContest = obj as Contest;
            if (objAsContest == null) return false;
            return Equals(objAsContest);
        }

        public bool Equals(Contest other)
        {
            if (other == null) return false;
            return Id == other.Id;
        }

        public int CompareTo(Contest other)
        {
            var tempX = new DateTime();
            var tempY = new DateTime();
            tempX = Convert.ToDateTime(StartTime);
            tempY = Convert.ToDateTime(other.StartTime);
            var result = DateTime.Compare(tempX, tempY);

            if (result < 0)
            {
                return -1;
            }
            if (result == 0)
            {
                return 0;
            }
            return 1;
        }

        public void SaveContestToXmlFile(string fileName)
        {
            Stream stream = null;
            try
            {
                stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.Write);
                var xs = new XmlSerializer(typeof (Contest));
                xs.Serialize(stream, this);
            }
            catch (Exception)
            {
                throw new Exception("Contest::SaveContestToFile - Exception while writing to file");
            }
            finally
            {
                if (stream != null)
                {
                    stream.Close();
                }
            }

            
        }

        public void AddDiverToRegister(string name, string gender, string personalcodenumber, string nationality, string club)
        {
            var d = new Diver(name,gender,personalcodenumber,nationality,club);
            DiverRegister.Add(d);
        }

        public void AddJudgeToRegister(string name, string gender, string personalcodenumber, string nationality, string affilliate)
        {
            var j = new Judge(name,gender,personalcodenumber,nationality,affilliate);
            JudgeRegister.Add(j);
        }

        public void AddDiverToEvent(string pnum, int eventId)
        {
            var tempDiver = new DiverWithJumpCodes();
            tempDiver.Diver = FindDiverInRegister(pnum);
            var e = new Event {Id = eventId};
            EventList[EventList.IndexOf(e)].AddDiver(tempDiver.Diver.Name,tempDiver.Diver.Gender,tempDiver.Diver.PersonalCodeNumber,tempDiver.Diver.Nationality,tempDiver.Diver.Club);
        }

        public void AddJudgeToEvent(string pnum, int eventId)
        {
            var tempJudge = new Judge();
            tempJudge = FindJudgeInRegister(pnum);
            var e = new Event {Id = eventId};
            EventList[EventList.IndexOf(e)].AddJudge(tempJudge);
        }

        public Diver FindDiverInRegister(string pnum)
        {
            var diverFound = DiverRegister.SingleOrDefault(d => d.PersonalCodeNumber == pnum);
            if (diverFound != null) return diverFound;
            throw new Exception("\nContest.FindDiverInRegister - Couldn't find diver in register");
        }

        public Judge FindJudgeInRegister(string pnum)
        {
            var judgeFound = JudgeRegister.SingleOrDefault(j => j.PersonalCodeNumber == pnum);
            if (judgeFound != null) return judgeFound;

            throw new Exception("\nContest.FindJudgeInRegister - Couldn't find judge in register");
        }

        public int GetNumberOfDivers()
        {
            return DiverRegister.Count;
        }

        public int GetNumberOfJudges()
        {
            return JudgeRegister.Count;
        }

        public void SortEventList()
        {
            var sortedList = EventList.OrderBy(x => x.StartTime).ToList();
            EventList = new BindingList<Event>(sortedList);
        }

        #endregion

    }

}